home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-03-08 | 7.6 KB | 226 lines | [TEXT/ALFA] |
-
- XTCLs (CopyRight 1992 by Tim Endres, modified by Pete Keleher)
-
- The tcl external command interface is similar to the HyperCard external
- command interface. Your code is a stand alone module that exists as a
- resource in the common XTCL File or in a file by itself.
-
- The advantage of having your XTCL in a separate file is the ability to have
- access to your own set of resources that are always carried around with the
- XTCL. The disadvantage is the cost of opening and close the XTCL's file
- every time it is executed.
-
- When Alpha is asked to execute the external command, it loads the resource
- from the (1) application resource fork, (2) the XTCL File resource fork, or (3)
- the resource fork of the optional file parameter. The resource is locked
- down in memory, and called as a C function. The external command's C
- code should begin as:
-
- void
- XTCLEntry(argc, argv, xpb)
- long argc;
- char **argv;
- XTCLParmBlk *xpb;
-
- The parameters are similar to what you would expect any C type program
- to take, except for the xpb parameter block. This parameter block is your
- link back into Alpha. Here is the structure:
-
- typedef struct {
- -> long version;
- <-> long result;
- <-> Handle resultH;
- -> short cmdRefNum;
- -> Handle cmdHandle;
- -> Tcl_Interp *interp;
- -> int (*eval)();
- -> ModalFilterProcPtr modalproc;
- - long reserved;
- } XTCLParmBlk, *XTCLPBPtr;
-
- The version field is passed in to indicate to the command what level of
- functionality the tcl callback function supports, as well as indicate the
- version of the parameter block data structure. The current version number
- of defined by XTCL_CB_VERSION in the header file XTCL.h and is currently
- 0x00010001.
-
- The result field is returned by the external command and is to be one of
- the predefined constants in XTCL.h. The resultH field contains a handle
- that is allocated by Alpha, with a length of zero, and passed to the external
- command to contain the results of the command. The command will resize
- the handle to hold its result, and copy the results into the handle's memory
- before returning. The external command should never dispose of the
- handle passed in resultH.
-
- The cmdRefNum field is the file system reference number of the file
- containing the XTCL command. Remember, this reference number may be
- the application's reference number or the number of the XTCL File, if the
- command was found in either of these locations. The external command
- must never close this file.
-
- The cmdHandle field is the handle to the code resource that contains the
- external command itself. It will be locked. Do not unlock, move, modify, or
- otherwise mutilate this memory!!!! Consider the handle and data READ
- ONLY.
-
- The interp field is a tcl interpreter pointer to the interpreter that called the
- external command.
-
- The eval field is a C procedure pointer to the callback routine to evaluate a
- tcl statement. It is equivalent to using the eval tcl command. The callback is
- used as follows:
-
- result = (* xpb->eval)(xpb, sHandle, rHandle, stdoutHandle);
-
- Where:
- 'xpb' is the parameter block pointer passed to the external command.
- 'sHandle' is a handle containing a null terminated string to be evaluated by the tcl
- interpreter.
- 'rHandle' is a handle for the result of the command. It may be zero length, but if it is
- not the results will be placed after the data already in the handle (as determined by
- GetHandleSize). The result will not be null terminated, thus, GetHandleSize must
- be used to determine the length of the result. This field may be NULL.
- 'stdoutHandle' is a handle for the standard output of the command. This is the
- output generated by the print command and error reporting. It may be zero length,
- but if it is not the results will be placed after the data already in the handle (as
- determined by GetHandleSize). The results will not be null terminated, thus,
- GetHandleSize must be used to determine the length of the result. This
- field may be NULL.
-
- The modalproc field is a procedure pointer to use in the
- ModalFilterProcPointer field of ModalDialog and the like.
-
- The reserved field is reserved.
-
-
- Two example XTCLs created in Think C 5.04 are in the 'xtcls' directory.
- The first merely returns a result based on its arguments. The second uses
- the 'eval' field of the XTCLParmBlk to have Alpha evaluate a script which
- adds a menu of all available sounds to Alpha's menubar. Selecting one of
- the menu items calls back into the XTCL and plays the sound. A compiled
- version of this XTCL is loaded into the Alpha binary. Use it by going to
- the home directory in the Tcl shell (cd <cr>), and then typing "xtclcmd
- sounds init".
-
- When creating XTCLs in ThinkC:
- 1) Global data is fine, but static initialization of pointers to the
- addresses of global data is not.
- 2) Except for the MacTraps library, all the libraries use global data. In
- order to use them in your code resource, you must make a copy that
- uses register a4 instead of a5 to reference global data. Make a copy
- of the library you need, and change the project type to 'Code
- Resource'.
- 3) Remember that 'argc' is passed as a long.
-
-
- An external command in MPW C should look like:
-
- #include "xtcl.h"
-
- void
- XTCLEntry(argc, argv, xpb)
- int argc;
- char **argv;
- XTCLParmBlk *xpb;
- {
- char *ptr, state;
- int i, length, slen;
-
- xpb->result = TCL_OK;
-
- length = GetHandleSize(xpb->resultH);
-
- for (i=1; i < argc; i++)
- slen += strlen(argv[i]) + 1;
-
- SetHandleSize(xpb->resultH, slen+1);
-
- state = HGetState(xpb->resultH);
- HLock(xpb->resultH);
-
- for (ptr=*xpb->resultH, i=1; i < argc; i++) {
- strcat(ptr, argv[i]);
- strcat(ptr, " ");
- ptr += strlen(ptr);
- }
-
- HSetState(xpb->resultH, state);
- }
-
- And would be linked together with:
-
- XTCL_echo ƒ ∂
- XTCL_echo.c.o
- Echo '#' Linking XTCL_echo
- Link -t "XTCL" -c "MPS " ∂
- -rt "XTCL=2020" ∂
- -sg "echo" ∂
- -m XTCLEntry ∂
- -o XTCL_echo ∂
- XTCL_echo.c.o ∂
- {CLibraries}StdCLib.o ∂
- {Libraries}Interface.o
-
- NOTE: The -sg "echo" option in the Link command will determined the
- name of the code resource that is produced, and thus the name of the
- external command. The -rt "XTCL=2020" option in the Link command
- determines the resource type of the code generated, and its resource id.
- The resource type must be XTCL, and the resource ID should try to be
- unique, but is not critical.
-
- Also remember that stand alone C code must not use global variables, and
- must use the -b option when calling the C compiler to use string constants.
-
- Finally, the following code fragment is an example of an XTCL that simply
- calls the eval callback routine with its first argument to be evaluated.
-
- #include "xtcl.h"
-
- void
- XTCLEntry(argc, argv, xpb)
- int argc;
- char **argv;
- XTCLParmBlk *xpb;
- {
- long length;
- int result;
- Handle rHandle, sHandle;
- char *script = argv[1];
-
- xpb->result = TCL_OK;
-
- length = strlen(script);
- sHandle = NewHandle(length+1);
- rHandle = NewHandle(0);
-
- if (sHandle != NULL && rHandle != NULL)
- {
- strcpy(*sHandle, script);
-
- result = (* xpb->eval)(xpb, sHandle, rHandle, NULL);
-
- length = GetHandleSize(rHandle);
- SetHandleSize(xpb->resultH, length + 1);
- if (MemError() == noErr) {
- memcpy(*xpb->resultH, *rHandle, GetHandleSize(rHandle));
- * (*xpb->resultH + length) = '\0';
- }
- else
- result = TCL_ERROR;
-
- xpb->result = result;
- }
-
- if (sHandle != NULL)
- DisposHandle(sHandle);
- if (rHandle != NULL)
- DisposHandle(rHandle);
- }
-
-
-
- NOTE: Pascal programmers will need to link with the Pascal glue code to
- work. The glue code provides a C entry that will call your Pascal routine for
- the XTCL. It also provides glue to callback the interpreter for evaluation.
- Please see the example sources and makefile for further details.
-